package com.yx.common.core.utils;

import cn.hutool.core.util.HexUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * java 正则匹配基本操作工具类
 * 1. 多行匹配
 * 2. 已支持 . (默认正则 不支持) 匹配所有字符包括换行
 * <p>
 *
 * @author kai.yang
 * @date 2022/11/17 17:34
 **/
public final class RegexUtils {

    /**
     * 缓存一些 Pattern.compile() 的
     */
    private static final Map<String, Pattern> PATTERN = new HashMap<>();

    private RegexUtils() {
    }

    public static String get(String regex, String content) {
        return get(regex, content, 0);
    }

    public static String get(String regex, String content, int groupIndex) {
        return get(getPattern(regex), content, groupIndex);
    }

    public static String get(Pattern pattern, String content) {
        return get(pattern, content, 0);
    }

    public static String get(Pattern pattern, String content, int groupIndex) {
        Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            return matcher.group(groupIndex);
        }
        return null;
    }

    /**
     * 获取匹配项
     *
     * @param regex
     * @param input
     * @return 返回一个list集合类型的匹配项
     * @see #getMatcherList(String, CharSequence, int)
     */
    public static List<String> getMatcherList(String regex, CharSequence input) {
        return getMatcherList(regex, input, 0);
    }

    /**
     * 获取匹配项
     *
     * @param regex
     * @param input
     * @param group //group(0) 返回符合条件的字符串,  group(1) 表示正则表达式中符合条件的字符串中的第一个() 中的字符串。
     * @return 返回一个list集合类型的匹配项
     * @see #getMatcherList(String, CharSequence)
     */
    public static List<String> getMatcherList(String regex, CharSequence input, int group) {
        List<String> list = new ArrayList<>();
        forEach(regex, input, matcher -> list.add(matcher.group(group)));
        return list;
    }

    /**
     * 迭代匹配，更自由的操作，一般无需直接操作改方法，除非你有更复杂的场景。
     *
     * @param regex
     * @param input
     * @param consumer
     * @see #getMatcherList(String, CharSequence, int)
     * @see #findAny(String, CharSequence)
     */
    public static void forEach(String regex, CharSequence input, Consumer<Matcher> consumer) {
        Matcher matcher = getMatcher(getPattern(regex), input);
        while (matcher.find()) {
            consumer.accept(matcher);
        }
    }

    /**
     * 非贪婪模式匹配，是否有匹配项
     *
     * @param regex
     * @param input
     * @return true，存在指定规则的匹配数据
     */
    public static boolean findAny(String regex, CharSequence input) {
        //默认贪婪是匹配，如果仅仅查询是否有匹配项，直接是否非贪婪即可，性能更好，哪怕这种性能微乎其微
        return findAny(getPattern("^" + regex), input);
    }

    public static boolean findAny(Pattern pattern, CharSequence input) {
        return getMatcher(pattern, input).find();
    }

    /**
     * 是否匹配
     *
     * @param regex
     * @param input
     * @return
     */
    public static boolean matches(String regex, CharSequence input) {
        return getMatcher(getPattern(regex), input).matches();
    }

    /**
     * 优先会找缓存，找不到再初始化
     *
     * @param regex 标准的正则表达式
     * @return
     */
    private static Pattern getPattern(String regex) {
        Pattern pattern = PATTERN.getOrDefault(regex, Pattern.compile(regex,Pattern.DOTALL | Pattern.MULTILINE));
        PATTERN.put(regex, pattern);
        return pattern;
    }

    /**
     * 获取匹配器,会缓存匹配器
     *
     * @param pattern
     * @param input
     * @return
     */
    private static Matcher getMatcher(Pattern pattern, CharSequence input) {
        if (pattern == null) {
            return null;
        }
        String regex = pattern.pattern();
        if (!PATTERN.containsKey(regex)) {
            PATTERN.put(regex, pattern);
        }
        return pattern.matcher(input);
    }

    /**
     * 获取匹配项
     *
     * @param regex
     * @param input
     * @param group //group(0) 返回符合条件的字符串,  group(1) 表示正则表达式中符合条件的字符串中的第一个() 中的字符串。
     * @return 返回一个list集合类型的匹配项
     * @see #getMatcherList(String, CharSequence)
     */
    public static String replaceHexConvertStr(String regex, CharSequence input, int group) {
        List<String> list = new ArrayList<>();
        Matcher matcher = getMatcher(getPattern(regex), input);
        while (matcher.find()) {
            String mc = matcher.group(group);
            input =  input.toString().replace(mc,HexUtil.decodeHexStr(mc.substring(1)));
        }
        return input.toString();
    }

    /**
     *@desc 是否地址URL
     *@params [urls]
     *@return boolean
     *@author baolian.sun
     *@date 2023/4/19
     */
    public static boolean isUrl(String urls) {
        if(StringUtils.isBlank(urls)) {
            return  true;
        }
        String regex = "(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\&%\\+\\$#_=]*)?";

        Pattern pat = Pattern.compile(regex);
        Matcher mat = pat.matcher(urls.trim());
        boolean result = mat.matches();
        return result;
    }


    /**
     *  shifou shuzi kaitou
     * @author sunbaolian
     * @date 2024/1/11 18:23
     * @param str
     * @return boolean
     */
    public static boolean startsWithNumber(String str) {
        Pattern pattern = Pattern.compile("^\\d");
        Matcher matcher = pattern.matcher(str);
        return matcher.find();
    }


}

